class PageHandler{
    constructor(ops,init){
        
        this.default = ops;

        this.binds = ops['binds'];
        //dom被订阅者 dom被订阅者 : 变量订阅者是 1:1
        this.domSubjectArr = [];
        //变量被订阅者  变量被订阅者 : dom订阅者 1:n
        this.varSubjectArr = {};

        if(init){
            this.init();
        }
    }
    init(){
        let allDom = document.getElementsByTagName("*");
        if(allDom != null && this.binds){
            for(let i = 0; i < allDom.length;i++){
                let currDom = allDom[i];
                let bindField = currDom.getAttribute("data-bind");
                if(bindField !=null && bindField.replace(/\s/g,"").length > 0){
                   let field = bindField.replace(/\s/g,"");
                   if(this.binds.hasOwnProperty( field )){
                        //建立(dom订阅者)
                        let domObs = new DomObserver(currDom);
                        //判断是否已经存在此(dom订阅者)对应的(变量被订阅者),没有就添加
                         
                        if(!this.varSubjectArr.hasOwnProperty( field )){
                            this.varSubjectArr[field] = new VarSubject(this.binds , field , this.binds[field]);
                        }
                        this.varSubjectArr[field].addObserver(domObs);

                        //如果dom是可改变的元素,建立(变量订阅者)
                        if(currDom.nodeName == 'INPUT'){

                            let domSub = new DomSubject(currDom);
                            let varObs = new VarObserver(this.binds , field);
                            domSub.addObserver(varObs);
                            this.domSubjectArr.push(domSub);
                        }else{
                            console.log(currDom.nodeName + "非input无法改变，所以不订阅")
                        }
                   }
                }
            }
        }
        //激活初始
        for(let key in this.binds){
            this.binds[key] = this.binds[key];
        }
    }
}

//变量类型的被订阅者
class VarSubject{
    constructor(obj,field,val){
        this.obj = obj;
        this.field = field;
        this.observerArr = [];
        let thiz = this;
        Object.defineProperty(obj, field, {
            get:function(){
                console.log(field + "被读取了" + val);
                if(typeof val === "function"){
                    return val();
                }
                return val;
            },
            set:function(newVal){
                console.log(field + "被写入了:" + newVal);
                thiz.notify(newVal);
                val = newVal;
            }
        })
    }
    //添加订阅者
    addObserver(observer){
        this.observerArr.push(observer);
    }
    //通知订阅者
    notify(newval){
        this.observerArr.forEach(function(obs){
            obs.update(newval);
        })
    }
}

//dom类型的被订阅者
class DomSubject{
    constructor(dom){
        this.dom = dom;   
        this.observerArr = [];
        let thiz = this;
        if(dom.nodeName == 'INPUT'){
            if(dom.type=='text'){
                dom.oninput=function(){
                    thiz.notify(dom.value);
                };
            }else{
                console.log(dom.nodeName + "-" + dom.type + "暂时未添加监听变更")
            }
        }else{
            console.log(dom.nodeName + "暂时不支持监听变更")
        }
    }
    //添加订阅者
    addObserver(observer){
        this.observerArr.push(observer);
    }
    //通知订阅者
    notify(newval){
        this.observerArr.forEach(function(obs){
            obs.update(newval);
        })
    }
}

//变量订阅者
class VarObserver{
    constructor(obj,field){
        this.obj = obj;
        this.field = field;
    }
    update(newVal){
            this.obj[this.field] = newVal;
    }
}

//dom订阅者
class DomObserver{
    constructor(dom){
        this.dom = dom;
    }
    update(newVal){
        let val = newVal;
        if(typeof newVal === "function"){
            val = newVal();
        }
        if(this.dom.nodeName == 'INPUT'){
            if(this.dom.type=='text'){
                this.dom.value = val;
            }
            if(this.dom.type=='checkbox'){
                console.log("checkbox暂不支持");
            }
        }else{
            if('innerHTML' in this.dom){
                this.dom.innerHTML = val;
            }else{
                console.log(this.dom.nodeName + "暂不支持变更");
            }
        }
    }
}